package com.wzh.codegen.biz.service.impl;

import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wzh.codegen.api.domain.dto.DatasourceQuery;
import com.wzh.codegen.biz.domain.dto.DatasourceDTO;
import com.wzh.codegen.biz.domain.entity.Datasource;
import com.wzh.codegen.biz.mapper.DatasourceMapper;
import com.wzh.codegen.biz.service.DatasourceService;
import com.wzh.common.general.exception.CustomerException;
import com.wzh.common.general.result.PageQuery;
import com.wzh.common.general.result.PageResult;
import com.wzh.common.general.util.ConditionHandler;
import com.wzh.common.mybatis.util.MybatisPageUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * 数据源服务实现类
 *
 * @author wzh
 * @since 2024-01-01
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DatasourceServiceImpl extends ServiceImpl<DatasourceMapper, Datasource> implements DatasourceService {

    @Override
    public PageResult<DatasourceDTO> page(PageQuery<DatasourceQuery> pageQuery) {
        if (pageQuery == null) {
            pageQuery = new PageQuery<>();
        }

        DatasourceQuery query = pageQuery.getQuery();
        if (query == null) {
            query = new DatasourceQuery();
        }

        Page<Datasource> page = MybatisPageUtils.createPage(pageQuery);

        QueryWrapper<Datasource> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(CharSequenceUtil.isNotBlank(query.getName()), "name", query.getName())
                .eq(CharSequenceUtil.isNotBlank(query.getDbType()), "db_type", query.getDbType());

        // 处理排序
        MybatisPageUtils.handleOrderBy(queryWrapper, pageQuery, "create_time");

        Page<Datasource> datasourcePage = page(page, queryWrapper);

        return MybatisPageUtils.toPageResult(datasourcePage, DatasourceDTO.class);
    }


    @Override
    public DatasourceDTO getByIdVo(Long id) {
        Datasource datasource = this.getById(id);
        if (datasource == null) {
            throw new CustomerException("数据源不存在");
        }
        return MybatisPageUtils.convert(datasource, DatasourceDTO.class);
    }

    @Override
    public void create(DatasourceDTO dto) {
        testConnection(dto);
        Datasource datasource = MybatisPageUtils.convert(dto, Datasource.class);
        save(datasource);
        log.info("创建数据源成功，ID: {}, 名称: {}", dto.getId(), dto.getName());
    }

    @Override
    public void update(DatasourceDTO dto) {
        Datasource datasource = MybatisPageUtils.convert(dto, Datasource.class);
        ConditionHandler.branchOrThrow(
                !updateById(datasource),
                () -> new CustomerException("数据源不存在")
        );
        log.info("更新数据源成功，ID: {}, 名称: {}", dto.getId(), dto.getName());
    }

    @Override
    public void delete(Long id) {
        ConditionHandler.branchOrThrow(
                !removeById(id),
                () -> new CustomerException("数据源不存在")
        );
        log.info("删除数据源成功，ID: {}", id);
    }

    @Override
    public String testConnection(DatasourceDTO dto) {
        try {
            Class.forName(dto.getDriverClassName());
            try (Connection connection = DriverManager.getConnection(
                    dto.getUrl(), dto.getUsername(), dto.getPassword())) {
                if (connection != null && !connection.isClosed()) {
                    log.info("数据源连接测试成功，名称: {}", dto.getName());
                    return "连接成功";
                } else {
                    throw new CustomerException("连接失败");
                }
            }
        } catch (ClassNotFoundException e) {
            log.error("数据库驱动未找到", e);
            throw new CustomerException("数据库驱动未找到: " + e.getMessage());
        } catch (SQLException e) {
            log.error("数据源连接测试失败", e);
            throw new CustomerException("连接失败: " + e.getMessage());
        }
    }

}